/**
  ******************************************************************************
  * @file    operators.h
  * @author  Amaseing team
  * @version V1.0.0
  * @date    21-november-2013
  * @brief   Vision operators
  *         
  ******************************************************************************  
  */ 
#ifndef _OPERATORS_H_
#define _OPERATORS_H_

/* Public includes -----------------------------------------------------------*/
#include <stm32f4xx.h>
#include "image.h"
#include "math.h"

/* Public defines ------------------------------------------------------------*/
//Threshold
#define DARK 				(0)
#define BRIGHT 			(1)
#define LIGHT 			(BRIGHT)

//Color detection
#define COLOR_OBJECT_SIZE_MIN		(5)

#ifndef NULL
	#define NULL 0
#endif


//Connected
enum eCONNECTED{
	FOUR = 0,
	EIGHT,
};

//Colors
//For every color defined here, must be a set of color constants in colorconst[]
enum eCOLOR{
	COLOR_GREEN = 0,
	COLOR_RED,
	COLOR_BLUE,
	COLOR_SIZE //the size of the enum eCOLOR
};

typedef struct colorconstants {
	uint8_t color; //color of enum eCOLOR
	uint8_t lowCb;
	uint8_t lowCr;
	uint8_t highCb;
	uint8_t highCr;
	uint8_t lowluma;
	uint8_t highluma;
} colorconstants_t;

typedef struct colorobject {
	uint16_t color; //color from eCOLOR
	uint16_t xstart;
	uint16_t xstop;
	uint16_t ystart;
	uint16_t ystop;
	uint16_t object;
} colorobject_t;

static const colorconstants_t colorconst[] = {
	//Color,  		lowCb, 		lowCr,  	highCb, 	highCr, 		lowLuma, 		highluma
	{COLOR_GREEN, 	0, 			0, 			118, 		115, 			100, 			255}, //M180
	{COLOR_RED, 	80, 		157, 		120, 		225, 			60,				255}, //
	{COLOR_BLUE, 	150, 		90, 		180, 		118, 			100,			255}  //

//{COLOR_XXX, 	0, 			0, 			0, 			0}
};

/* Public functions ----------------------------------------------------------*/
//Converts YUV to a grayscale value in fields Y0 and Y1
void camConvertLumaToGrayScale(image_t *img);

//Calculate the Mean value of 3 rows and writes the result in the first row
void vCalculateMeanOfThreeRows(image_t *img);

//Filter Luma using the median method
void vMedianYUVLumaFilter(image_t *img);

//Filter Cr&Cb using the median method
void vMedianYUVColorFilter(image_t *img);

//Histogram for grayscale and YUV using Y0 and Y1 fields
void vHistogram(image_t  *src,
                uint16_t *hist);
								
//Threshold grayscale and YUV using Y0 and Y1 fields
//Fields Cb and Cr will be 0
void vThreshold(image_t *src,
                image_t *dst, // result is a binary image
                uint8_t low,
                uint8_t high);
								
//Threshold ISODATA using Y0 and Y1 fields
//Fields Cb and Cr will be 0
void vThresholdIsoData(image_t *src,
						image_t *dst,
                       uint32_t brightness); // DARK | BRIGHT/LIGHT
											  
									 
//Threshold YUV color using Cb and Cr fields
//Color need to be one of enum eCOLOR
//Result 1 or 0 is stored in Y0 and Y1 fields
//Fields Cb and Cr will be 0
void vThresholdYUVColor(image_t *img,
												enum eCOLOR color);					
												
//Scan row for one color using constants of colorconst[]			
//Color need to be one of enum eCOLOR
//Returns -1: error
//				0: no color found
//			  1: color found
//
//Object data will be stored in obj
int iScanRowForColor(image_t *img, 
											enum eCOLOR color,
											colorobject_t *obj);
											
//Scan row for all colors defined in enum eCOLOR using constants of colorconst[]
//Returns -1: error
//				0: no color found
//			>=1: one or more colors found
//
//Object data will be stored in obj
int iScanRowForColors(image_t *img, 
											colorobject_t *obj,
											int8_t size);

//Scan column for all colors defined in enum eCOLOR using constants of colorconst[]
//Returns -1: error
//				0: no color found
//			>=1: one or more colors found
//
//Object data will be stored in obj											
int iScanColumnForColors(image_t *img, 
											enum eCOLOR color, 
											colorobject_t *obj);
											
//Set selected to value
//Function uses only Y0 and Y1 fields
void vSetSelectedToValue(image_t *src,
                         image_t *dst,
                         uint8_t selected,
                         uint8_t value);
//Fill holes
//Function effects only Y0 and Y1 fields
//Image must be a binary image
//Fields Cb and Cr must be 0
void vFillHoles(image_t *src, 
                image_t *dst,
                enum eCONNECTED connected); // FOUR | EIGHT	
								
//Set selected to value
//Function effects only Y0 and Y1 fields		
//Image must be a binary image
//Fields Cb and Cr must be 0
void vRemoveBorderBlobs(image_t *src, 
                        image_t *dst,
                        enum eCONNECTED connected); // FOUR | EIGHT																				
//Lable the blobs
//Function uses Y0 and Y1 fields for binairy information
//Image must be a binary image
//Fields Cb and Cr must be 0
//Output will be a 16bit alligned value between 0 and 255
//Return value returns the number of blobs that are found
uint32_t iLabelBlobs(image_t *img,
                     enum eCONNECTED connected); // FOUR | EIGHT	
										 
//Count Neighbours with the same value
//Function uses only Y0 and Y1 fields
uint8_t iNeighbourCount(image_t *img,
                        uint16_t x,
                        uint16_t y,
                        uint16_t value,
                        enum eCONNECTED connected); // FOUR | EIGHT	
												
//Calculate centroid of blob											
void vCentroid(image_t *img, uint8_t blobnr, uint8_t *xc, uint8_t *yc, uint32_t* m00);

//Calculate central moments
double dNormalizedCentralMoments(image_t *img, 
																uint8_t blobnr, 
																int p, 
																int q,
																uint8_t xc, 
																uint8_t yc, 
																uint32_t m00);

#endif /*_OPERATORS_H_*/


